﻿using System;
using System.Web;
using NHibernate.Cfg;
using NHibernate.Cfg.Loquacious;
using NHibernate.ByteCode.Castle;
using NHibernate.Dialect;
using NHibernate.Connection;
using NHibernate.Driver;
using NHibernate;
using System.Data;
using NHibernate.AdoNet;
using NHibernate.Transaction;
using NHibernate.Exceptions;
using DomainModel;
using System.Collections.Generic;
using System.Threading;
using log4net;
using System.Reflection;


namespace DAL
{
    /// <summary>
    /// session工厂，向应用程序提供session
    /// chenjing 2009-4-15
    /// </summary>
    public sealed class SessionManager 
    {
        private const string CurrentSessionKey = "nhibernate.current_session";
        public static readonly ISessionFactory sessionFactory;
        private static Dictionary<string, ISession> dictionary = new Dictionary<string, ISession>();


        static SessionManager()
        {
            var cfg = new Configuration();
            cfg.SessionFactory()
               .Integrate
                    .Using<MsSql2008Dialect>()
                    .DisableKeywordsAutoImport()
                    .AutoQuoteKeywords()
                    //.LogSqlInConsole()
                    .DisableLogFormatedSql()
                    .Connected
                        .Through<DriverConnectionProvider>()
                        .By<SqlClientDriver>()
                        .With(IsolationLevel.ReadCommitted)
                        .Releasing(ConnectionReleaseMode.AfterTransaction)
                        //.Using("Server=192.168.0.13;Database=ts_keywords;Uid=u_keys;Pwd=p_keys_#01;")
                        .Using(System.Configuration.ConfigurationManager.AppSettings["serv1"])
                    .BatchingQueries
                        .Through<SqlClientBatchingBatcherFactory>()
                        .Each(15)
                    .Transactions
                         .Through<AdoNetTransactionFactory>()
                    .CreateCommands
                        //.Preparing()
                        .WithTimeout(10)
                        .ConvertingExceptionsThrough<SQLStateConverter>()
                        .AutoCommentingSql()
                        .WithMaximumDepthOfOuterJoinFetching(11)
                        .WithHqlToSqlSubstitutions("true 1, false 0, yes 'Y', no 'N'");
                    //.Schema
                       // .Validating();
            cfg.SessionFactory()
                .Proxy
                    .DisableValidation()
                    .Through<NHibernate.ByteCode.Castle.ProxyFactoryFactory>();
            cfg.SessionFactory()
                .GeneratingCollections
                    .Through<NHibernate.Type.DefaultCollectionTypeFactory>();
            cfg.AddAssembly("DomainModel");
            
            sessionFactory = cfg.BuildSessionFactory();

        }

        public static ISession GetCurrentSession()
        {
            HttpContext context = HttpContext.Current;
            ISession currentSession = null;
            if (context == null) {
                string key = Thread.GetDomainID() + Thread.CurrentThread.GetHashCode().ToString();
                if (dictionary.ContainsKey(key))
                {
                    currentSession = dictionary[key] as ISession;
                }
                else
                {
                    currentSession = sessionFactory.OpenSession();
                    ILog log4 = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
                    log4.Info("dictionary.Add(" + key + ")" + dictionary.ContainsKey(key));
                    Console.WriteLine("dictionary.Add(" + key + ")" + dictionary.ContainsKey(key));
                    dictionary.Add(key,currentSession);
                }

            }
            else{
                currentSession = context.Items[CurrentSessionKey] as ISession;

                if (currentSession == null)
                {
                    currentSession = sessionFactory.OpenSession();
                    context.Items[CurrentSessionKey] = currentSession;
                }
            }

            return currentSession;
        }

        public static void CloseSession()
        {
            HttpContext context = HttpContext.Current;
            ISession currentSession;
            if (context == null)
            {
                string key = Thread.GetDomainID() + Thread.CurrentThread.GetHashCode().ToString();
                if (!dictionary.ContainsKey(key))
                {
                    return;
                }
                currentSession = dictionary[key] as ISession;
                currentSession.Close();
                ILog log4 = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
                log4.Info("dictionary.Remove(" + key + ")" + dictionary.ContainsKey(key));
                Console.WriteLine("dictionary.Add(" + key + ")" + dictionary.ContainsKey(key));
                dictionary.Remove(key);
            }
            else
            {
                currentSession = context.Items[CurrentSessionKey] as ISession;

                if (currentSession == null)
                {
                    // No current session
                    return;
                }

                currentSession.Close();
                context.Items.Remove(CurrentSessionKey);
            }
        }

        public static void CloseSessionFactory()
        {
            if (sessionFactory != null)
            {
                sessionFactory.Close();
            }
        }
    }
}